package cn.edu.qzuie.artist.module.td.service.major;

import cn.edu.qzuie.artist.framework.common.exception.ErrorCode;
import cn.edu.qzuie.artist.framework.common.exception.ServiceException;
import cn.edu.qzuie.artist.module.td.api.school.TdSchoolApi;
import cn.edu.qzuie.artist.module.td.api.school.dto.TdSchoolSelectRespDTO;
import cn.edu.qzuie.artist.module.td.controller.admin.department.vo.DepartmentForSelectVo;
import cn.edu.qzuie.artist.module.td.dal.dataobject.classinfo.ClassinfoDO;
import cn.edu.qzuie.artist.module.td.dal.dataobject.department.DepartmentDO;
import cn.edu.qzuie.artist.module.td.dal.dataobject.school.SchoolDO;
import cn.edu.qzuie.artist.module.td.dal.mysql.classinfo.ClassinfoMapper;
import cn.edu.qzuie.artist.module.td.service.department.DepartmentService;
import cn.edu.qzuie.artist.module.td.service.school.SchoolService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;

import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import cn.edu.qzuie.artist.module.td.controller.admin.major.vo.*;
import cn.edu.qzuie.artist.module.td.dal.dataobject.major.MajorDO;
import cn.edu.qzuie.artist.framework.common.pojo.PageResult;
import cn.edu.qzuie.artist.framework.common.pojo.PageParam;
import cn.edu.qzuie.artist.framework.common.util.object.BeanUtils;

import cn.edu.qzuie.artist.module.td.dal.mysql.major.MajorMapper;

import javax.annotation.Resource;

import static cn.edu.qzuie.artist.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.edu.qzuie.artist.module.td.enums.ErrorCodeConstants.*;

/**
 * 专业 Service 实现类
 *
 * @author 泉信管理员
 */
@Service
@Validated
public class MajorServiceImpl implements MajorService {

    @Resource
    private MajorMapper majorMapper;
    @Resource
    private TdSchoolApi tdSchoolApi;
    @Resource
    private DepartmentService departmentService;
    @Resource
    private SchoolService schoolService;
    @Resource
    private ClassinfoMapper classinfoMapper;

    @Override
    public Long createMajor(MajorSaveReqVO createReqVO) {
        // 插入
        MajorDO major = BeanUtils.toBean(createReqVO, MajorDO.class);
        if (isMajorExists(createReqVO.getMajorName(), createReqVO.getDepartId(), null)) {
            throw exception(MAJOR_ALREADY_EXISTS);
        }
        majorMapper.insert(major);
        // 返回
        return major.getId();
    }

    @Override
    public void updateMajor(MajorSaveReqVO updateReqVO) {
        // 校验存在
        validateMajorExists(updateReqVO.getId());
        if (isMajorExists(updateReqVO.getMajorName(), updateReqVO.getDepartId(), updateReqVO.getId())) {
            throw exception(MAJOR_ALREADY_EXISTS);
        }
        // 更新
        MajorDO updateObj = BeanUtils.toBean(updateReqVO, MajorDO.class);
        majorMapper.updateById(updateObj);
    }


    @Override
    public void deleteMajor(Long id) {
        // 校验此专业下是否存在班级，若不存在，直接删除；存在，则需要把该专业下的所有的班级删除后，才可以删除此专业
        Long classCount = classinfoMapper.selectCount(new cn.edu.qzuie.artist.framework.mybatis.core.query.LambdaQueryWrapperX<ClassinfoDO>()
                .eq(ClassinfoDO::getMajorId, id));
        if (classCount == 0) {
            // 删除
            majorMapper.deleteById(id);
        } else {
            throw exception(MAJOR_EXISTS_Class);
        }
    }

    private void validateMajorExists(Long id) {
        if (majorMapper.selectById(id) == null) {
            throw exception(MAJOR_NOT_EXISTS);
        }
    }

    /**
     * 校验专业信息是否已经存在
     *
     * @param majorName 专业名称
     * @param departId  部门ID
     * @param excludeId 排除的ID，用于更新时检查
     * @return 是否存在
     */
    private boolean isMajorExists(String majorName, Long departId, Long excludeId) {
        // 校验专业是否存在
        MajorDO major = majorMapper.selectOne(new cn.edu.qzuie.artist.framework.mybatis.core.query.LambdaQueryWrapperX<MajorDO>()
                .eq(MajorDO::getMajorName, majorName)
                .eq(MajorDO::getDeleted, 0)
                .eq(MajorDO::getDepartId, departId));
        return major != null && !major.getId().equals(excludeId);
    }


    @Override
    public MajorDO getMajor(Long id) {
        return majorMapper.selectById(id);
    }

    @Override
    public PageResult<MajorDO> getMajorPage(MajorPageReqVO pageReqVO) {
        return majorMapper.selectPage(pageReqVO);
    }

    @Override
    public List<SchoolDepartForTreeVo> createSchoolDepartmentTree() {
        List<TdSchoolSelectRespDTO> schools = tdSchoolApi.getSchool();
        Assert.notNull(schools, "学校数据不能为空");

        return schools.stream()
                .map(school -> {
                    SchoolDepartForTreeVo schoolNode = new SchoolDepartForTreeVo();
                    BeanUtils.copyProperties(school, schoolNode);

                    Long schoolId = school.getId();
                    List<DepartmentForSelectVo> departments = departmentService.getDepartments(schoolId);
                    Assert.notNull(departments, "学校ID[" + schoolId + "]对应的部门不能为空");

                    schoolNode.setChildren(departments);
                    return schoolNode;
                })
                .collect(Collectors.toList());
    }

    @Override
    public PageResult<MajorAndDepartNameRespVo> getMajorAndDepartNameRespVoPage(MajorPageReqVO pageReqVO) {
        PageResult<MajorDO> pageResult = majorMapper.selectPage(pageReqVO);
        System.out.println("查询到的数据为：" + pageResult.getList());
        List<MajorDO> majorDOList = pageResult.getList();

        if (majorDOList.isEmpty()) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }

        Set<String> majorNames = new HashSet<>(); // 用于存储已经存在的专业名称

        List<MajorAndDepartNameRespVo> majorAndDepartNameRespVoList = majorDOList.stream()
                .filter(majorDO -> majorNames.add(majorDO.getMajorName())) // 添加并检查是否重复
                .map(majorDO -> {
                    MajorAndDepartNameRespVo respVo = new MajorAndDepartNameRespVo();
                    BeanUtils.copyProperties(majorDO, respVo);
                    DepartmentDO departmentDO = departmentService.getDepartment(majorDO.getDepartId());
                    if (departmentDO != null) {
                        respVo.setDepartName(departmentDO.getDepartName());
                        SchoolDO schoolDO = schoolService.getSchool(departmentDO.getSchoolId());
                        respVo.setSchoolName(schoolDO.getSchoolName());
                    }
                    return respVo;
                })
                .collect(Collectors.toList());

        PageResult<MajorAndDepartNameRespVo> result = new PageResult<>();
        result.setList(majorAndDepartNameRespVoList);
        result.setTotal((long) majorAndDepartNameRespVoList.size());

        System.out.println("专业的数据为：" + result);
        return result;
    }


    @Override
    public List<MajorForSelectVo> getMajors(Long schoolId) {
        // 通过学校的id查找对应的部门数据
        List<DepartmentForSelectVo> departments = departmentService.getDepartments(schoolId);
        if (departments.isEmpty()) {
            return Collections.emptyList();
        }
        // 初始化一个Set来存储已经存在的专业名称
        Set<String> majorNames = new HashSet<>();
        // 初始化结果列表
        List<MajorForSelectVo> majorForSelectVos = new ArrayList<>();
        // 遍历部门的数据去查找每个部门下的专业的数据
        for (DepartmentForSelectVo department : departments) {
            List<MajorDO> majorDOs = majorMapper.selectList("depart_id", department.getId());
            for (MajorDO majorDO : majorDOs) {
                // 使用Set检查专业是否已经存在，并且只在不存在时添加
                if (majorNames.add(majorDO.getMajorName())) { // 如果成功添加，则表示该专业名称之前不存在
                    MajorForSelectVo majorForSelectVo = new MajorForSelectVo();
                    BeanUtils.copyProperties(department, majorForSelectVo);
                    majorForSelectVo.setMajorName(majorDO.getMajorName());
                    majorForSelectVo.setId(majorDO.getId());
                    majorForSelectVos.add(majorForSelectVo);
                }
            }
        }
        // 返回该学校下的所有部门下的专业的数据
        return majorForSelectVos;
    }

}